//package com.zhang.common.batch;
//
//import com.zhang.common.db.DruidDataSourceBuilder;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.batch.core.partition.support.Partitioner;
//import org.springframework.batch.item.ExecutionContext;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.PostConstruct;
//import javax.sql.DataSource;
//import java.sql.Connection;
//import java.sql.ResultSet;
//import java.sql.Statement;
//import java.util.HashMap;
//import java.util.Map;
//
///**
// * ActivityCouponMigratePartitioner
// *
// * @author zhangxin
// * @date 2021/5/20
// */
//@Component
//public class CommonPartitioner implements Partitioner {
//    private static final Logger logger = LoggerFactory.getLogger(ActivityCouponMigratePartitioner.class);
//    public static final String FROM = "from";
//    public static final String TO = "to";
//    public static final String PARTITION_KEY = "partition-";
//    private static final String SQL = "SELECT CouponId FROM activity_coupon_base WHERE ActiveFlag = 1 AND ( now() <= EndTime OR EndTime is NULL ) ORDER BY CouponId";
//    private static final String PK = "CouponId";
//    private DataSource dataSource;
//
//    @Autowired
//    private DruidDataSourceBuilder druidDataSourceBuilder;
//
//    public CommonPartitioner() {
//        //empty
//    }
//
//    @PostConstruct
//    public void init() {
//        this.dataSource = druidDataSourceBuilder.build();
//    }
//
//    @Override
//    public Map<String, ExecutionContext> partition(int gridSize) {
//        logger.info("ActivityCouponMigratePartitioner, gridSize : {}", gridSize);
//        Map<String, ExecutionContext> result = new HashMap<>();
//        ResultSet rs = null;
//        Connection conn = null;
//        Statement st = null;
//
//        try {
//            String sql = SQL;
//            conn = dataSource.getConnection();
//            st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
//            logger.info("partition sql: {}", sql);
//            rs = st.executeQuery(sql);
//            rs.last();
//            int rowCount = rs.getRow();
//            if(rowCount != 0) {
//                rs.first();
//                //每区数量
//                int slop = rowCount / gridSize;
//                //多余记录平均分配到各分区, 即每区数量+1
//                int tmpSlop = slop + 1;
//                //有多余记录的分区数
//                int tmpPart = rowCount % gridSize;
//                //没有多余记录的分区数
//                int part = gridSize - tmpPart;
//                int pos = 0;
//                logger.info("rowCount:{}, slop:{}, tmpSlop:{}, part:{}, tmpPart:{}, from:{}",
//                        rowCount, slop, tmpSlop, part, tmpPart, rs.getObject(PK));
//                if (slop == 0) {
//                    ExecutionContext context = new ExecutionContext();
//                    context.put(FROM, rs.getObject(PK));
//                    rs.last();
//                    context.put(TO, rs.getObject(PK));
//                    logger.info("slop:{}, part:{}, pos:{}, to:{}", slop, 0, pos, rs.getObject(PK));
//                    result.put(PARTITION_KEY + slop, context);
//                    return result;
//                } else {
//                    for(int i = 0; i < gridSize; ++i) {
//                        ExecutionContext context = new ExecutionContext();
//                        //rowCount:912, gridSize:60, slop:15, tmpSlop:16, part:48, tmpPart:12, from:52960550
//                        //每区数量, 前tmpPart分区数量为tmpSlop, 其余分区数量为slop
//                        int tmp = i > tmpPart - 1 ? slop : tmpSlop;
//                        logger.info("slop:{}, part:{}, pos:{}, from:{}", tmp, i, pos, rs.getObject(PK));
//                        context.put(FROM, rs.getObject(PK));
//                        if (i == gridSize - 1) {
//                            rs.last();
//                            logger.info("slop:{}, part:{}, pos:{}, to:{}", tmp, i, pos, rs.getObject(PK));
//                            context.put(TO, rs.getObject(PK));
//                        } else {
//                            rs.relative(tmp - 1);
//                            logger.info("slop:{}, part:{}, pos:{}, to:{}", tmp, i, pos, rs.getObject(PK));
//                            context.put(TO, rs.getObject(PK));
//                        }
//
//                        result.put(PARTITION_KEY + i, context);
//                        logger.debug("partition {}: {}", pos, context);
//                        pos += tmp;
//                        rs.next();
//                    }
//                    return result;
//                }
//            }
//
//        } catch (Exception e) {
//            logger.error(e.getLocalizedMessage(), e);
//        } finally {
//            close(conn, st, rs);
//        }
//        return null;
//    }
//
//    /**
//     * 关闭连接
//     * @param conn
//     * @param st
//     * @param rs
//     */
//    private void close(Connection conn, Statement st, ResultSet rs) {
//        if(rs != null) {
//            try {
//                rs.close();
//            } catch (Exception e) {
//                logger.error(e.getLocalizedMessage(), e);
//            }
//        }
//        if(st != null) {
//            try {
//                st.close();
//            } catch (Exception e) {
//                logger.error(e.getLocalizedMessage(), e);
//            }
//        }
//        if(conn != null) {
//            try {
//                conn.close();
//            } catch (Exception e) {
//                logger.error(e.getLocalizedMessage(), e);
//            }
//        }
//    }
//}
